﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IPlugin;
using System.Threading;
using System.IO;
using System.Web;
using System.Xml;

namespace Plugin
{
    class Plugin : IPlugin.IPlugin
    {
        private string htmlFileName = "index.html";
        private StringBuilder stringBuilder;
        private TempSensorThread tst;
        public string Name
        {
            get { return "GetTemperature"; }
        }
        public string Version
        {
            get { return "1.0 Beta"; }
        }

        public Plugin()
        {
            try
            {
                tst = new TempSensorThread();
                Thread sensorThread = new Thread(tst.Run);
                sensorThread.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in Temperature-Plugin:\nServer muss beendet werden.\nDetail: " + ex.Message);
                Console.Read();
                Environment.Exit(0);
            }

            FileStream fs = null;
            StreamReader sr = null;
            try
            {
                fs = File.OpenRead("Plugins\\" + Name + '\\' + htmlFileName);
                sr = new StreamReader(fs);
                stringBuilder = new StringBuilder("");
                while (!sr.EndOfStream)
                {
                    stringBuilder.Append(sr.ReadLine());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: Temperature-Plugin\nDetail: " + ex.Message);
                Console.Read();
                Environment.Exit(0);
            }
            finally
            {
                if (fs != null)
                    fs.Close();
                if (sr != null)
                    sr.Close();
            }
        }
        public string getXmlFromRestRequest(int year, int month, int day)
        {
            DateTime date = new DateTime(year, month, day);
            List<string[]> list = tst.getTempsOfDay(date);
            if (list == null)
            {
                //Error bei Datenbankabfrage
                return "Error bei DB";
            }

            XmlDocument doc = new XmlDocument();
            XmlNode root = doc.CreateElement("Temperaturenliste");
            doc.AppendChild(root);
            foreach (string[] sary in list)
            {
                XmlNode nodeEintrag = doc.CreateElement("Eintrag");
                root.AppendChild(nodeEintrag);
                XmlNode nodeZeit = doc.CreateElement("Uhrzeit");
                XmlNode nodeTemp = doc.CreateElement("Temperatur");
                nodeZeit.InnerText = sary[0];
                nodeTemp.InnerText = sary[1];
                nodeEintrag.AppendChild(nodeZeit);
                nodeEintrag.AppendChild(nodeTemp);
            }

            return doc.OuterXml;
        }
        public Response ExecutePlugin(Request req)
        {
            string decodedPath = HttpUtility.UrlDecode(req.ReqUrl.Path); //z.B. %20 umwandeln zu ' '
            if (!decodedPath.Equals("/"))
                decodedPath = decodedPath.TrimEnd('/');
            string[] separatedBlocks = decodedPath.Split('/');

            string htmlOutput = stringBuilder.ToString();
            Response resp = new Response(req.getSocket());

            if (separatedBlocks.Length == 5)
            {
                //Es wurden 4 Bloecke getrennt durch Slash eingegeben. -> pruefen auf gueltige REST-Abfrage
                int year;
                int month;
                int day;
                if (int.TryParse(separatedBlocks[2], out year) == false || int.TryParse(separatedBlocks[3], out month) == false || int.TryParse(separatedBlocks[4], out day) == false)
                {
                    //Datum ungueltig
                    htmlOutput = "<html><head><title>REST-Abfrage</title></head><body><h1>Ung&uuml;ltige REST-Abfrage</h1><p>Das angegebene Datum ist nicht g&uuml;ltig.</p></body></html>";

                    resp.StatusCode = 200;
                    resp.StatusText = "OK";
                    resp.ContentType = "text/html";
                    resp.Data = htmlOutput;
                    return resp;
                }

                try
                {
                    resp.StatusCode = 200;
                    resp.StatusText = "OK";
                    resp.ContentType = "text/xml";
                    resp.Data = getXmlFromRestRequest(year, month, day);
                    return resp;
                }
                catch (ArgumentOutOfRangeException)
                {
                    //Datum ungueltig
                    htmlOutput = "<html><head><title>REST-Abfrage</title></head><body><h1>Ung&uuml;ltige REST-Abfrage</h1><p>Das angegebene Datum ist nicht g&uuml;ltig.</p></body></html>";

                    resp.StatusCode = 200;
                    resp.StatusText = "OK";
                    resp.ContentType = "text/html";
                    resp.Data = htmlOutput;
                    return resp;
                }
            }

            int rowsInDb = tst.getNumberOfRowsInDb();
            double pages = double.Parse(rowsInDb.ToString()) / tst.LimitSize;
            pages = Math.Ceiling(pages);
            if (rowsInDb == -1)
            {
                //Datenbank-Error
                resp.StatusCode = 200;
                resp.StatusText = "OK";
                resp.ContentType = "text/html";
                resp.Data = "Datenbank-Error bei Temperaturenabfrage. Bitte versuchen Sie es sp&auml;ter erneut.";
                return resp;
            }

            List<string[]> list = null;
            int page = 1;
            int pageBack = 1;
            int pageNext = 1;
            StringBuilder content = new StringBuilder();

            if (req.ReqPostVars != null && req.ReqPostVars.ParameterList != null)
            {
                if (req.ReqPostVars.ParameterList.ContainsKey("searchInputField"))
                {
                    string searchDate = req.ReqPostVars.ParameterList["searchInputField"];
                    if (!string.IsNullOrWhiteSpace(searchDate))
                    {
                        DateTime dateObject = new DateTime();
                        try
                        {
                            dateObject = Convert.ToDateTime(searchDate);
                            list = tst.getTempsOfDay(dateObject);
                            pages = 1;
                            rowsInDb = list.Count;
                            content.Append("<p>Temperaturen am " + dateObject.Day + "." + dateObject.Month + "." + dateObject.Year + " &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; >> <a href='/" + this.Name + "'>Zeige alle Daten</a> <<</p>");
                        }
                        catch (FormatException)
                        {
                            //User hat kein korrektes Datum eingegeben
                            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Content}", "<p>Das eingegebene Datum ist nicht korrekt. >> <a href='/" + this.Name + "'>Zeige alle Daten</a> <<</p>");
                            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Entries}", "0");
                            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Pages}", "1 / 1");
                            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Chart}", "");
                            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Back}", "1");
                            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Next}", "1");

                            resp.StatusCode = 200;
                            resp.StatusText = "OK";
                            resp.ContentType = "text/html";
                            resp.Data = htmlOutput;
                            return resp;
                        }
                    }
                    else
                    {
                        //User hat kein korrektes Datum eingegeben
                        htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Content}", "<p>Das eingegebene Datum ist nicht korrekt. >> <a href='/" + this.Name + "'>Zeige alle Daten</a> <<</p>");
                        htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Entries}", "0");
                        htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Pages}", "1 / 1");
                        htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Chart}", "");
                        htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Back}", "1");
                        htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Next}", "1");

                        resp.StatusCode = 200;
                        resp.StatusText = "OK";
                        resp.ContentType = "text/html";
                        resp.Data = htmlOutput;
                        return resp;
                    }
                }
            }
            else if (req.ReqUrl.HasParameter)
            {
                Dictionary<string, string> paramDict = req.ReqUrl.ParameterList;
                if (paramDict.Keys.Contains("page"))
                {
                    bool b = int.TryParse(paramDict["page"], out page);
                    if (b)
                    {
                        if (page <= 1)
                        {
                            page = 1;
                            pageBack = 1;
                            pageNext = 2;
                        }
                        else if (page >= pages)
                        {
                            page = int.Parse(pages.ToString());
                            pageBack = page - 1;
                            pageNext = page;
                        }
                        else
                        {
                            pageBack = page - 1;
                            pageNext = page + 1;
                        }

                        list = tst.getTempsByLimit((page - 1) * tst.LimitSize);

                    }
                    else
                    {
                        list = tst.getTempsByLimit(0);
                        if (pages != 1)
                            pageNext = 2;
                    }
                }
                else
                {
                    list = tst.getTempsByLimit(0);
                    if (pages != 1)
                        pageNext = 2;
                }
            }
            else
            {
                list = tst.getTempsByLimit(0);
                if (pages != 1)
                    pageNext = 2;
            }


            //Standard Webseitenaufruf...


            if (list == null)
            {
                //Datenbank-Error
                resp.StatusCode = 200;
                resp.StatusText = "OK";
                resp.ContentType = "text/html";
                resp.Data = "Datenbank-Error bei Temperaturenabfrage. Bitte versuchen Sie es sp&auml;ter erneut.";
                return resp;
            }

            content.Append("<tr><th>Datum</th><th>Temperatur</th>");
            StringBuilder chart = new StringBuilder();
            int i = 0;
            foreach (string[] sary in list)
            {
                if (i % 2 == 0)
                    content.Append("<tr class='style1'><td>" + sary[0] + "</td><td>" + sary[1] + "</td></tr>");
                else
                    content.Append("<tr class='style2'><td>" + sary[0] + "</td><td>" + sary[1] + "</td></tr>");
                i++;

                DateTime date = new DateTime();
                try
                {
                    date = Convert.ToDateTime(sary[0]);
                    chart.Append(" [new Date(" + date.Year + "," + (date.Month - 1) + "," + date.Day + "," + date.Hour + "," + date.Minute + "," + date.Second + "), " + sary[1] + "],");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Conversion-Error: " + ex.Message);
                }
            }



            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Content}", content.ToString());
            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Entries}", rowsInDb.ToString());
            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Pages}", page + " / " + pages);
            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Chart}", chart.ToString());
            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Back}", pageBack.ToString());
            htmlOutput = htmlOutput.Replace("{Embedded-Sensor-Cloud-Next}", pageNext.ToString());

            resp.StatusCode = 200;
            resp.StatusText = "OK";
            resp.ContentType = "text/html";
            resp.Data = htmlOutput;

            return resp;
        }
    }
}
